﻿/*
 * KRPCService
 * 
 * Hold all information of a KRPC service
 * 
 * Author: snowdreamist
 * Date: 2011/12/7
 * 
 */
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using BitTorrentSharp.KRPC.Contract;
using BitTorrentSharp.KRPC.Handler;

namespace BitTorrentSharp.KRPC
{
    public class KRPCService
    {
        internal KRPCService(Type serviceType)
        {
            if (serviceType == null)
                throw new ArgumentNullException("serviceType");
            // wrapper
            this.ContractWrapper = new ServiceContractWrapper(serviceType);
            // operations
            this.Operations = new ObservableCollection<KRPCOperation>(this.LoadOperations());
            // intance
            this.Intance = ServiceInstanceHandler.CreateHandler(
                this.ContractWrapper.ServiceType,
                this.ContractWrapper.InstanceMode,
                this.ContractWrapper.CustomInstanceFactory);
        }
        /// <summary>
        /// Service contract wrapper
        /// </summary>
        public ServiceContractWrapper ContractWrapper { get; private set; }
        /// <summary>
        /// Operations
        /// </summary>
        public ObservableCollection<KRPCOperation> Operations { get; private set; }
        /// <summary>
        /// Service instance
        /// </summary>
        public ServiceInstanceHandler Intance { get; private set; }

        #region private
        
        private List<KRPCOperation> LoadOperations()
        {
            List<KRPCOperation> operations = new List<KRPCOperation>();
            // operation contract
            var methods = this.ContractWrapper.ServiceType.GetMethods();
            if (methods == null)
                return operations;
            foreach (var method in methods)
            {
                // if a operation
                var optAttrs = method.GetCustomAttributes(typeof(KRPCOperationContractAttribute), false);
                if (optAttrs != null && optAttrs.Length == 1)
                {
                    // a operation
                    operations.Add(new KRPCOperation(this, method, optAttrs[0] as KRPCOperationContractAttribute));
                }
            }

            return operations;
        }
        #endregion
    }
}
